package com.zenchn.utils;


import org.apache.tomcat.util.buf.HexUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * DES 加密解密工具类
 *
 * DES是一种对称加密算法，所谓对称加密算法即：加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究，
 * 后来被美国政府正式采用，之后开始广泛流传，但是近些年使用越来越少，因为DES使用56位密钥，以现代计算能力，
 * 24小时内即可被破解。
 *
 * @author dingxinfa
 * @date 2019-12-02
 */
public class DESUtils {


    private static final String DES_NAME = "DES";
    private static final String CHARSET = "UTF-8";


    /***
     * 加密  返回byte
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(String source, String key) throws Exception {
        return encrypt(source.getBytes(CHARSET), key);
    }

    /***
     * 加密  返回byte
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] source, String key) throws Exception {
        byte[] encodeByte = encryptOrDecrypt(Cipher.ENCRYPT_MODE, source, key);
        return encodeByte;
    }


    /***
     * 加密  返回Hex(16进制)  字符
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptToHexString(byte[] source, String key) throws Exception {
        byte[] encodeByte = encrypt(source, key);
        return HexUtils.toHexString(encodeByte);
    }

    /***
     * 加密  返回Hex(16进制)  字符
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptToHexString(String source, String key) throws Exception {
        byte[] encodeByte = encrypt(source, key);
        return HexUtils.toHexString(encodeByte);
    }


    /***
     * 加密  返回Base64 字符
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptToBase64String(String source, String key) throws Exception {
        byte[] encodeByte = encrypt(source, key);
        return Base64.getEncoder().encodeToString(encodeByte);
    }


    /**
     * 解密  byte,返回 byte
     *
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] source, String key) throws Exception {
        byte[] decodeByte = encryptOrDecrypt(Cipher.DECRYPT_MODE, source, key);
        return decodeByte;
    }

    /**
     * 解密 Hex(16进制),返回 byte
     *
     * @param source Hex(16进制)字符
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptHex(String source, String key) throws Exception {
        return decrypt(HexUtils.fromHexString(source), key);
    }

    /**
     * 解密 Base64,返回 byte
     *
     * @param source Base64字符
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBase64(String source, String key) throws Exception {
        return decrypt(Base64.getDecoder().decode(source), key);
    }

    /**
     * 解密  byte,返回 String
     *
     * @param source
     * @param key
     * @return
     * @throws Exception
     */
    public static String decryptToString(byte[] source, String key) throws Exception {
        byte[] decodeByte = decrypt(source, key);
        String decodeStr = new String(decodeByte, CHARSET);
        return decodeStr;
    }


    /**
     * 解密 Hex(16进制),,返回 String
     *
     * @param source Hex(16进制)字符
     * @param key
     * @return
     * @throws Exception
     */
    public static String decryptHexToString(String source, String key) throws Exception {
        byte[] decodeByte = decryptHex(source, key);
        String decodeStr = new String(decodeByte, CHARSET);
        return decodeStr;
    }

    /**
     * 解密 Base64,返回 String
     *
     * @param source Base64字符
     * @param key
     * @return
     * @throws Exception
     */
    public static String decryptBase64ToString(String source, String key) throws Exception {
        byte[] decodeByte = decryptBase64(source, key);
        String decodeStr = new String(decodeByte, CHARSET);
        return decodeStr;
    }


    /***
     * 加解密调用
     * @param mode  加密 解密 模式
     * @param source   数据源
     * @param key   秘钥
     * @return
     * @throws Exception
     */
    private static byte[] encryptOrDecrypt(int mode, byte[] source, String key) throws Exception {
        // DES算法要求有一个可信任的随机数源
        SecureRandom random = new SecureRandom();
        // 创建一个DESKeySpec对象
        DESKeySpec desKey = new DESKeySpec(key.getBytes());
        // 创建一个密匙工厂
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_NAME);
        // 将DESKeySpec对象转换成SecretKey对象
        SecretKey securekey = keyFactory.generateSecret(desKey);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(DES_NAME);
        // 用密匙初始化Cipher对象
        cipher.init(mode, securekey, random);
        // 真正开始解密操作
        return cipher.doFinal(source);
    }


    public static void main(String args[]) {
        try {
            //待加密内容
            String str = "121212_平海大厦";
            //密码，长度要是8的倍数
            String password = "1qaz2wsx3edc";

            String encryptResult = encryptToHexString(str, password);
            System.out.println(encryptResult);

            //直接将如上内容解密

            String decryResult = decryptHexToString(encryptResult, password);
            System.out.println("解密后：" + new String(decryResult));
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}
